#include "systemclass.h"

static const unsigned int WINDOWED_WIDTH = 800;
static const unsigned int WINDOWED_HEIGHT = 600;

SystemClass::SystemClass():m_Input(0), m_Graphics(0)
{}

bool SystemClass::Initialize(bool isfullscreen)
{
	m_fullscreen = isfullscreen;

	if (isfullscreen)
	{
		m_screenwidth  = GetSystemMetrics(SM_CXSCREEN);
		m_screenheight = GetSystemMetrics(SM_CYSCREEN);
	}
	else
	{
		m_screenwidth   = WINDOWED_WIDTH;
		m_screenheight = WINDOWED_HEIGHT;
	}

	InitializeWindows();

	m_Input = new InputClass;
	bool result = m_Input->Initialize();
	if (!result) 
	{
		return false;
	}
	m_Graphics = new GraphicsClass;
	result = m_Graphics->Initialize(m_screenwidth, m_screenheight, m_hwnd);
	return result;
}

void SystemClass::Shutdown()
{
	if(m_Graphics)
	{
		m_Graphics->Shutdown();
		delete m_Graphics;
		m_Graphics = 0;
	}

	if(m_Input)
	{
		delete m_Input;
		m_Input = 0;
	}

	ShutdownWindows();
}

void SystemClass::Run()
{
	MSG msg;
	bool result;

	ZeroMemory(&msg, sizeof(MSG));
	
	bool quit = false;

	while(!quit)
	{
		if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}

		if(msg.message == WM_QUIT)
		{
			quit  = true;
		}
		else
		{
			result = Frame();
			quit = !result;
		}
	}
}

bool SystemClass::Frame()
{	
	if(m_Input->IsKeyDown(VK_ESCAPE))
	{
		return false;
	}

	bool result = m_Graphics->Frame(m_Input);
	
	return result;
}

LRESULT CALLBACK SystemClass::MessageHandler(HWND hwnd, UINT umsg, WPARAM wparam, LPARAM lparam)
{
	switch(umsg)
	{
		case WM_KEYDOWN:
		{
			m_Input->KeyDown((unsigned int)wparam);
			break;
		}

		case WM_KEYUP:
		{
			m_Input->KeyUp((unsigned int)wparam);
			break;
		}
		
		case WM_RBUTTONDOWN:
		{
			if ( (m_Input->IsMouseKeyDown((unsigned int)wparam)) == true)
			{
				m_Input->MouseKeyUp((unsigned int)wparam);
				break;
			}
			m_Input->MouseKeyDown((unsigned int)wparam);
			break;
		}

		default:
		{
			return DefWindowProc(hwnd, umsg, wparam, lparam);
		}
	}
}

void SystemClass::InitializeWindows()
{
	WNDCLASSEX wc;
	DEVMODE dmScreenSettings;
	int posX, posY;

	ApplicationHandle = this;

	m_hinstance = GetModuleHandle(NULL);

	m_applicationName = L"MD Engine";

	wc.style         = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
	wc.lpfnWndProc   = WndProc;
	wc.cbClsExtra    = 0;
	wc.cbWndExtra    = 0;
	wc.hInstance     = m_hinstance;
	wc.hIcon		 = LoadIcon(NULL, IDI_WINLOGO);
	wc.hIconSm       = wc.hIcon;
	wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
	wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
	wc.lpszMenuName  = NULL;
	wc.lpszClassName = m_applicationName;
	wc.cbSize        = sizeof(WNDCLASSEX);
	
	RegisterClassEx(&wc);

	if(m_fullscreen)
	{
		memset(&dmScreenSettings, 0, sizeof(dmScreenSettings));
		dmScreenSettings.dmSize       = sizeof(dmScreenSettings);
		dmScreenSettings.dmPelsWidth  = (unsigned long)m_screenwidth;
		dmScreenSettings.dmPelsHeight = (unsigned long)m_screenheight;
		dmScreenSettings.dmBitsPerPel = 32;			
		dmScreenSettings.dmFields     = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
		ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN);
		posX = posY = 0;
	}
	else
	{
		posX = (GetSystemMetrics(SM_CXSCREEN) - m_screenwidth)  / 2;
		posY = (GetSystemMetrics(SM_CYSCREEN) - m_screenheight) / 2;
		/*to be removed*/
		posX = 1500; 
		posY = 900;
	}

	m_hwnd = CreateWindowEx(WS_EX_TOPMOST, m_applicationName, m_applicationName, 
						    /*WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_POPUP*/ WS_EX_TOOLWINDOW,
						    posX, posY, m_screenwidth, m_screenheight, NULL, NULL, m_hinstance, NULL);

	ShowWindow(m_hwnd, SW_SHOWDEFAULT);
	SetForegroundWindow(m_hwnd);
	UpdateWindow( m_hwnd );

	//ShowCursor(false);
}

void SystemClass::ShutdownWindows()
{
	//ShowCursor(true);
	if(m_fullscreen)
	{
		ChangeDisplaySettings(NULL, 0);
	}

	DestroyWindow(m_hwnd);
	UnregisterClass(m_applicationName, m_hinstance);
	
	m_hwnd = NULL;
	m_hinstance = NULL;
	ApplicationHandle = NULL;
}


LRESULT CALLBACK WndProc(HWND hwnd, UINT umessage, WPARAM wparam, LPARAM lparam)
{
	switch(umessage)
	{
		case WM_DESTROY:
		case WM_CLOSE:
		{
			PostQuitMessage(0);		
			return 0;
		}

		default:
		{
			return ApplicationHandle->MessageHandler(hwnd, umessage, wparam, lparam);
		}
	}
}